package com.zm.blog.utils.storage;

import com.zm.blog.handle.BlogRuntimeException;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.stereotype.Component;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;

import java.util.Collections;
import java.util.HashMap;
import java.util.Map;

/**
 * @Author: Sister Xiao Ming
 * @Description: 文件存储服务，用于对接多个存储平台
 *
 * FileStorageService类。它实现了ApplicationContextAware接口，用于在Spring容器启动时获取所有StoreService类型的bean，
 * 并将其存储在一个以storeName为key的Map中。同时，它提供了两个方法根据storeType获取对应的存储服务
 */
@Slf4j
@Component
public class FileStorageService implements ApplicationContextAware {

    @Value("${store.type}")
    private String defaultType;

    //使用不可修改的Map确保线程安全
    private final Map<String, StoreService> storeServiceMap = new HashMap<>();

    @Override
    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
        Map<String, StoreService> beansOfType = applicationContext.getBeansOfType(StoreService.class);
        if (CollectionUtils.isEmpty(beansOfType)) {
            log.warn("未找到任何存储平台实现！");
            return;
        }
        for (StoreService storeService : beansOfType.values()) {
            String storeName = storeService.getStoreName();
            if (storeServiceMap.containsKey(storeName)) {
                log.warn("发现重复的存储平台名称：{}", storeName);
            }
            storeServiceMap.put(storeName, storeService);
        }
        log.info("已加载存储平台：{}", storeServiceMap.keySet());
    }

    /**
     * 获取指定的存储平台（必须提供有效存储类型）
     * @param storeType 存储类型
     */
    public StoreService getFileStorageByStoreType(String storeType) {
        validateStoreType(storeType);
        return getStoreService(storeType);
    }

    /**
     * 获取存储平台（可自动使用默认类型）
     *
     * @param storeType 存储类型（可选）
     * @return 存储服务实例
     */
    public StoreService getFileStorage(String storeType) {
        if (!StringUtils.hasText(storeType)) {
            storeType = defaultType;
        }
        return getStoreService(storeType);
    }

    /**
     * 获取所有的存储平台
     * @return
     */
    public Map<String, StoreService> getAllStorages() {
        return Collections.unmodifiableMap(storeServiceMap);
    }

    /**
     * 内部方法：获取存储服务并验证
     * @param storeType
     * @return
     */
    private StoreService getStoreService(String storeType) {
        validateStoreType(storeType);

        StoreService service = storeServiceMap.get(storeType);
        if (service == null) {
            throw new BlogRuntimeException("没有找到对应的存储平台：{}" + storeType);
        }
        return service;
    }

    /**
     * 验证存储平台是否有效
     * @param storeType
     */
    private void validateStoreType(String storeType) {
        if (!StringUtils.hasText(storeType)) {
            throw new BlogRuntimeException("存储类型不能为空！");
        }
    }


}
